/*
 * 
 *
 * Created on March 22, 2007, 12:34 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

//package edu.byu.isys413.pb88.data;
package finalintex2web;
import java.util.*;
import java.io.*;
import java.sql.*;

/**
 *
 * @author prabol
 */
public abstract class PhysicalProductDAO extends ProductDAO 
{
    
    
    /** Creates a new instance of PhysicalProductDAO */
    public PhysicalProductDAO() 
    {
        super();
    }
    protected static ProductDAO instance = null;
        
    /*public static synchronized ProductDAO getInstance()
    {
        if (instance == null) {
            instance = new PhysicalProductDAO();
        }
        return instance;
    }*/
    
   /* public ProductBO create()
    {
        String id = GUID.generate();
        // super.create();
         PhysicalProductBO pp = new  PhysicalProductBO(id);
        Cache c = Cache.getInstance();
        c.put(pp.getId(),pp);
        return pp;
    }*/
    public abstract PhysicalProductBO create();
    
    public PhysicalProductBO read(String id) throws DataException,ConnectionPoolException
    {
        
        try
        {
            Connection conn = ConnectionPool.getInstance().get();
            PhysicalProductBO prod = (PhysicalProductBO)read(id,conn);
            ConnectionPool.getInstance().release(conn);
            return prod;
        }
        catch (SQLException e)
        {
            // rollback
            throw new DataException("SQL error from read 1", e);
        }
        catch (ConnectionPoolException e)
        {
            throw new ConnectionPoolException("Connection pool error in read 1", e);
        }
    }
    private PhysicalProductBO read(String id, Connection conn) throws SQLException, DataException, ConnectionPoolException
    {

        if(Cache.getInstance().containsKey(id))
        {
            PhysicalProductBO prod = (PhysicalProductBO)Cache.getInstance().get(id);
            return prod;
         }      
         try
         {        
           PreparedStatement stmt = conn.prepareStatement("SELECT * FROM Physical WHERE physicalid=?");
           stmt.setString(1,id);
           ResultSet rs =  stmt.executeQuery();
           
           ConnectionPool.getInstance().release(conn);
            
            if (rs.next())
            {
                 super.read(id);
                 PhysicalProductBO prod = (PhysicalProductBO)Cache.getInstance().get(id);
                 prod.setPrice(rs.getDouble("Price"));
                 prod.setShelfLocation(rs.getString("ShelfLocation"));
                 prod.setDatePurchased(rs.getString("DatePurchased"));
                 prod.setSaleorRent(rs.getBoolean("saleorrent"));
                 prod.setSerialNumber(rs.getString("serialnumber"));
                 Cache.getInstance().put(id,prod);      
                 prod.setIndb(true);
                 stmt.close();
                 return prod;
               

            }
            else
            {
                throw new DataException("ProductBO was not found in the database.");
            }
           
            }
         catch (ConnectionPoolException e)
         {
                throw new ConnectionPoolException("Could not retrieve a connection from the database", e);
            
          }catch (SQLException e)
          {
                throw new DataException("SQL error", e);
            }
    }

    
    
    
    
    
    
    
    
    
         public synchronized void save(ProductBO product) throws DataException,ConnectionPoolException {
           System.out.println("in save of physical product"); 
        try
        {
            Connection conn = ConnectionPool.getInstance().get();
            save(product,conn);
            ConnectionPool.getInstance().release(conn);
        }
        catch (SQLException e)
        {
            //rollback
            throw new DataException("Could not retrieve record for id=" + product.getId(), e);
            
         }
        catch (ConnectionPoolException e)
        {
            //throw new ConnectionPoolException("Could not retrieve record for id=" + e);
                e.printStackTrace();
        }
        
        // release the connection back to the pool
        return;
    }
     synchronized void save(ProductBO product, Connection conn) throws SQLException, DataException, ConnectionPoolException 
     {
        // check the dirty flag in the RevenueSourceDBO.  if it is dirty, 
        // run update or insert
        if (product.isDirty()) 
        {
            if (product.isIndb()) 
            {
               update(product, conn);
            }
            else
            {
               insert(product, conn);
            }
            product.setDirty(false);
        Cache.getInstance().touch(product.getId());
     
        }
        
    }

    private synchronized void update(ProductBO product, Connection conn) throws SQLException, DataException, ConnectionPoolException{
        PreparedStatement stmt = conn.prepareStatement("UPDATE physical SET serialnumber=?,shelfLocation=?,DatePurchased=?,Saleorrent=? WHERE physicalid=? ");
        //super.save(revsrc,conn);
        super.save(product,conn);
        PhysicalProductBO pp = (PhysicalProductBO)product;
        stmt.setString(1,pp.getSerialNumber());
        stmt.setString(2,pp.getShelfLocation());
        stmt.setString(3,pp.getDatePurchased());
        stmt.setBoolean(4,pp.isSaleorRent());
        stmt.execute();
        stmt.close();
        ConnectionPool.getInstance().release(conn);
        
    }
    private synchronized void insert(ProductBO product, Connection conn) throws SQLException, DataException, ConnectionPoolException
    {
        PreparedStatement stmt = conn.prepareStatement("INSERT INTO Physical (physicalid,serialNumber,shelfLocation,datePurchased,saleorrent) VALUES ( ?,?,?,?,?)");
        super.save(product,conn);
        PhysicalProductBO pp = (PhysicalProductBO)product;
        stmt.setString(1,pp.getId());
        stmt.setString(2,pp.getSerialNumber());
        stmt.setString(3,pp.getShelfLocation());
        stmt.setString(4,pp.getDatePurchased());
        stmt.setBoolean(5,pp.isSaleorRent());
        stmt.execute();
        stmt.close();
        // tell the RevenueSourceDBO that it's now in the db (so we call update next time not insert)
        product.setIndb(true);
        ConnectionPool.getInstance().release(conn);
    }
}